package com.zjw.study.thread03_mutex;

/**
 * 线程互斥
 * 
 * @author Administrator
 *
 */
public class ThreadMutex {
	public static void main(String[] args) {
		ThreadMutex mutex = new ThreadMutex();
//		mutex.mutex01();
		mutex.mutex02();
	}

	/**
	 * 思考问题：输出时会遇到如
	 * wangermazihexiazhangsanhelisi
	 * owang
	 * 的情况，即线程互斥，应如何解决
	 */
	void mutex01() {
		final Print print = new Print();//是否两个线程共用一个输出对象都会出现问题
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					sleep();
					print.out("zhangsanhelisi");
				}
			}
		}).start();

		// --------------

		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					sleep();
					print.out("wangermazihexiaowang");
				}
			}
		}).start();
	}
	
	/**
	 * 使用synchronize解决sync01中线程互斥问题
	 */
	void mutex02() {
		final Print2 print = new Print2();//是否两个线程共用一个输出对象都会出现问题
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					sleep();
					print.out("zhangsanhelisi");
				}
			}
		}).start();

		// --------------

		/*new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					sleep();
					print.out2("wangermazihexiaowang");
				}
			}
		}).start();*/
		
		// --------------，1和2都不能与3互斥
		
		new Thread(new Runnable() {
			@SuppressWarnings("static-access")
			@Override
			public void run() {
				while(true) {
					sleep();
					print.out3("myname");
				}
			}
		}).start();
	}

	/**
	 * 线程休眠
	 */
	void sleep() {
		try {
			Thread.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}

/**
 * 打印信息
 * 
 * @author Administrator
 *
 */
class Print {
	/**
	 * 输出指定字符
	 * 
	 * @param str
	 */
	void out(String str) {
		int length = str.length();
		for (int i = 0; i < length; i++) {
			System.out.print(str.charAt(i));
		}
		System.out.println();
	}
}
class Print2 {
	/**
	 * 输出指定字符
	 * 
	 * @param str
	 */
	void out(String str) {
		int length = str.length();
//		synchronized (str) {//使用要打印的字符串不能避免问题
//		synchronized ("print") {//当两个线程进来是同一把锁时ok
//		synchronized (this) {//把当前类对象放进来，但不能与out2互斥
		synchronized (Print.class) {//把类的字节码做锁，实现与static的互斥
			for (int i = 0; i < length; i++) {
				System.out.print(str.charAt(i));
			}
			System.out.println();
		}
	}
	/**
	 * 输出内容
	 * @param str
	 */
	synchronized void out2(String str) {
		int length = str.length();
		for (int i = 0; i < length; i++) {
			System.out.print(str.charAt(i));
		}
		System.out.println();
	}
	/**
	 * 与out2不同的是static方法，却不能互斥
	 * @param str
	 */
	static synchronized void out3(String str) {
		int length = str.length();
		for (int i = 0; i < length; i++) {
			System.out.print(str.charAt(i));
		}
		System.out.println();
	}
}
